package com.wudimeng.syll.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wudimeng.syll.constants.Constants;
import com.wudimeng.syll.entity.CommonResult;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class _this {

    public static String datacenterId = "1";
    public static String machineId = "1";

    //加载雪花的配置文件
    static {
        final Properties properties = new Properties();
        try (final InputStream stream = Constants.class.getClassLoader().getResourceAsStream("config.properties")) {
            properties.load(stream);
            datacenterId = properties.getProperty("datacenterId");
            machineId = properties.getProperty("machineId");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取请求的IP
    public static String getIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if(StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if (StringUtils.isBlank(ip)) {
            StringTokenizer stringTokenizer = new StringTokenizer(ip, ",");
            if (stringTokenizer.countTokens() > 1) {
                return stringTokenizer.nextToken();
            }
        }
        return ip;
    }

    //判断是否是IE
    public static boolean isIE(HttpServletRequest request){
        try{
            String userAgent = request.getHeader("USER-AGENT").toLowerCase();
            boolean isIE11 = userAgent.indexOf("trident") > -1 && userAgent.indexOf("rv") > -1;
            return userAgent.contains("msie") || isIE11 ? true : false;
        }catch(Exception e){
            return false;
        }
    }

    //JSON输出给前端
    public static void jsonToWeb(JSONObject jsonObject, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        String jsonpcallback = request.getParameter("jsonpcallback");
        if (_this.isIE (request)) {
            response.setContentType("text/html;charset=UTF-8");
        } else {
            response.setContentType("application/json;charset=UTF-8");
        }
        PrintWriter printWriter = response.getWriter();
        if (StringUtils.isEmpty(jsonpcallback)) {
            printWriter.print(jsonObject.toString());
        } else {
            printWriter.print(jsonpcallback + "(" + jsonObject.toString() + ")");
        }
        printWriter.flush();
    }

    //JSON输出给前端
    public static void jsonToWeb(JSONArray jsonArray, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        String jsonpcallback = request.getParameter("jsonpcallback");
        if (_this.isIE (request)) {
            response.setContentType("text/html;charset=UTF-8");
        } else {
            response.setContentType("application/json;charset=UTF-8");
        }
        PrintWriter out = response.getWriter();
        if (StringUtils.isEmpty(jsonpcallback)) {
            out.print(jsonArray.toString());
        } else {
            out.print(jsonpcallback + "(" + jsonArray.toString() + ")");
        }
        out.flush();
    }

    //获取系统时间
    public static String nowTime(){
        SimpleDateFormat dateFormat = new SimpleDateFormat(Constants.DATETIME_FORMAT);
        return dateFormat.format(System.currentTimeMillis());
    }

    //获取系统时间
    public static String now(){
        SimpleDateFormat dateFormat = new SimpleDateFormat(Constants.DATE_FORMAT);
        return dateFormat.format(System.currentTimeMillis());
    }

    //日期计算，加xxx天
    public static Date addDay(Date date, Integer days) {
        if(date == null){
            return null;
        }
        if(days == null || days == 0){
            return date;
        }
        GregorianCalendar gc =new GregorianCalendar();
        gc.setTime(date);
        gc.add(GregorianCalendar.DATE, days);
        return gc.getTime();
    }

    //MAP转换成bean
    public static final <T> T mapToBean(T bean, Map<String, Object> sourceMap)
            throws IllegalAccessException, UnsupportedEncodingException {
        if(sourceMap == null) {
            return null;
        }
        for(Field field : bean.getClass().getDeclaredFields()) {
            if (Modifier.isFinal(field.getModifiers())) {
                continue;
            }
            if (field.getType() == Set.class || field.getType() == List.class || field.getType() == Map.class) {
                continue;
            }
            field.setAccessible(true);
            Object value = sourceMap.get(field.getName());
            if (value == null) {
                continue;
            }
            if (Objects.equals(value.getClass(), byte[].class)) {
                value = new String((byte[]) value, "utf-8");
            } else if (value.getClass() == Timestamp.class) {
                value = new Date(((Timestamp) value).getTime());
            } else if (value.getClass() == Double.class) {
                value = new BigDecimal(value.toString());
            }

            field.set(bean, value);
        }

        return bean;
    }

    //合并MAP
    public static <T> Map<String, T> mergeMap(Map<String, T> sourceMap1, Map<String, T> sourceMap2) {
        if (sourceMap2 == null || sourceMap2.size() == 0)
            return sourceMap1;
        if (sourceMap1 == null)
            sourceMap1 = new HashMap<String, T>();
        for (String key : sourceMap2.keySet()) {
            sourceMap1.put(key, sourceMap2.get(key));
        }
        return sourceMap1;
    }

    //JSON转换成MAP
    public static Map<String, Object> JsonToMap(JSONObject jsonObject) {
        if(jsonObject == null){
            return null;
        }

        Map<String, Object> resultMap = new HashMap<>();
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            resultMap.put(entry.getKey(), entry.getValue());
        }

        return resultMap;
    }

    //产生雪花ID
    public static String selectID() {
        try{
            Thread.sleep(100);
        }catch (Exception e){
            e.printStackTrace();
        }
        SnowFlake snowFlake = new SnowFlake(Long.valueOf(datacenterId), Long.valueOf(machineId));
        return String.valueOf(snowFlake.nextId());
    }

    //产生UUID
    public static String selectUUID() {
        String uuid = UUID.randomUUID().toString();
        uuid.replaceAll("-", "").toLowerCase();
        return uuid;
    }

    //比较两个时间的大小
    public static int compare_date(String DATE1, String DATE2) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date dt1 = (Date)df.parseObject(DATE1);
            Date dt2 = (Date)df.parseObject(DATE2);
            if (dt1.getTime() > dt2.getTime()) {
//                System.out.println("dt1 >dt2 ");
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
//                System.out.println("dt1<dt2 ");
                return -1;
            } else {
                return 0;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return 0;
    }

    /**
     * 当前时间所在一周的周一时间(或上周的时间)
     * @return
     */
    public static String getMondayWeekDate(boolean isLast) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        if(isLast){//上周的时间
            cal.add(Calendar.WEEK_OF_MONTH, -1);
        }
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if(dayWeek==1){
            dayWeek = 8;
        }
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - dayWeek);// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        Date mondayDate = cal.getTime();
        String mondayWeekDate = sdf.format(mondayDate);

        return mondayWeekDate;
    }

    /**
     * 每周之星排行 根据周数 获取其周一日期
     * @return
     */
    public static String getMondayWeekDateByWeekNum(Integer weekNum) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.add(Calendar.WEEK_OF_MONTH,0 - weekNum);
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if(dayWeek==1){
            dayWeek = 8;
        }
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - dayWeek);// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        Date mondayDate = cal.getTime();
        String mondayWeekDate = sdf.format(mondayDate);

        return mondayWeekDate;
    }

    /**
     * 当前时间所在月1号日期(或上月的时间)
     * @return
     */
    public static String getMonthFirstDay(boolean isLast) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        if(isLast){//上月1号
            cal.add(Calendar.MONTH, -1);
        }
        cal.set(Calendar.DAY_OF_MONTH, 1);
        String monthFirstDay = sdf.format(cal.getTime());

        return monthFirstDay;
    }


    /**
     * 每月之星排行 根据月数 获取其1号
     * @return
     */
    public static String getMonthFirstDayByMonthNum(Integer montHNum) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH,0 - montHNum);
        cal.set(Calendar.DAY_OF_MONTH, 1);//每月1号

        Date mondayDate = cal.getTime();
        String mondayWeekDate = sdf.format(mondayDate);

        return mondayWeekDate;
    }

    //    计算两个时间点的时间差几天
    public static long getDatePoor(Date endDate, Date nowDate) {

        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day;
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static String getWeekOfDate(Date date) {
        String[] weekDays = {"7", "1", "2", "3", "4", "5", "6"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    /**
     *  0 代表前面补充0
     * 4 代表长度为4
     * d 代表参数为正数型
     **/
    public static String formatNumber(Integer value, Integer length) {
        if(value == null){
            value = 0;
        }
        String result = String.format("%0" + length + "d", value);
        return result;
    }

    /**
     *  实体类转换JSONObject
     * @param result    返回接口实体类
     * @return 转换后的JSONObject类型
     */
    public static JSONObject entityToJson(CommonResult result){
        //实体类转换json字符转
        String jsonString = JSONObject.toJSONString(result);
        //json字符转转换JSONObject，并返回
        return JSONObject.parseObject(jsonString);

    }

    /**
     * 获取当前时间再当年的第几周   201942
     * @return
     * @throws Exception
     */
    public static String getWeekDateStr() throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date()); //当前时间
        Calendar cl = Calendar.getInstance();
        cl.setFirstDayOfWeek(Calendar.MONDAY);
        cl.setTime(sdf.parse(dateStr));
        int week = cl.get(Calendar.WEEK_OF_YEAR); //本周

        cl.setTime(new Date());
        cl.set(Calendar.DAY_OF_WEEK, 2); //设置 周一为第一天
        cl.set(Calendar.DATE, cl.get(Calendar.DATE) + 6); //设置后的当前时间 +6   为周日
        String year = sdf.format(cl.getTime()).substring(0,4);
        String newWeek = "0"+week;
        newWeek = newWeek.substring(newWeek.length()-2);
        String weekDate = year + newWeek;
        return weekDate;
    }

    /**
     * 获取上周再当年的第几周   201942  上周
     * @return
     * @throws Exception
     */
    public static String getLastWeekDateStr() throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_MONTH, -7);
        String start = sdf.format(c.getTime())+" 00:00:00";
        Calendar cl = Calendar.getInstance();
        cl.setFirstDayOfWeek(Calendar.MONDAY);
        cl.setTime(sdf.parse(start));
        int week = cl.get(Calendar.WEEK_OF_YEAR) ; //本周
        String year = sdf.format(cl.getTime()).substring(0,4);
        String newWeek = "0"+week;
        newWeek = newWeek.substring(newWeek.length()-2);
        String weekDate = year + newWeek;
        return weekDate;
    }

    /**
     * 获取当前时间 年
     * @return
     * @throws Exception
     */
    public static String getYearDate() throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date()); //当前时间
        Calendar cl = Calendar.getInstance();
        cl.setFirstDayOfWeek(Calendar.MONDAY);
        cl.setTime(sdf.parse(dateStr));
        int year = cl.get(Calendar.YEAR);
        String weekDate =  Integer.toString(year);
        return weekDate;
    }


    /**
     * 获取当前时间 周数
     * @return
     * @throws Exception
     */
    public static String getWeekDate() throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date()); //当前时间
        Calendar cl = Calendar.getInstance();
        cl.setFirstDayOfWeek(Calendar.MONDAY);
        cl.setTime(sdf.parse(dateStr));
        int week = cl.get(Calendar.WEEK_OF_YEAR);
        String weekDate =  Integer.toString(week);
        return weekDate;
    }

    /**
     * 获取当前时间 周数
     * @return
     * @throws Exception
     */
    public static String getLastWeekDate() throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date()); //当前时间
        Calendar cl = Calendar.getInstance();
        cl.setFirstDayOfWeek(Calendar.MONDAY);
        cl.setTime(sdf.parse(dateStr));
        int week = cl.get(Calendar.WEEK_OF_YEAR) - 1;
        String weekDate =  Integer.toString(week) ;
        return weekDate;
    }


}
